/*
 * Copyright 2007 Rob Nielsen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.proxymatic.core;

import com.googlecode.proxymatic.core.builder.ProxyObjectBuilder;
import com.googlecode.proxymatic.core.engine.JavaProxyEngine;

/**
 * This is a useful base class for extending to make a nice front end to ProxyBuilder.  You just need to override
 * setUpHandlerConfiguration() and add the method and exception handlers needed and some public methods that call
 * getProxyBuilder().proxy(...) and return the proxy object.  See the com.googlecode.proxymatic.apps package for
 * examples of it's use.
 */
public abstract class AbstractProxyApplication {
    private ProxyBuilder proxyBuilder;
    private ProxyEngine proxyEngine;

    /**
     * Implement this method to set up the handler configuration with your desired method and exception handlers. The
     * handlerConfiguration comes by default with support for equals(), hashCode(), toString() and exception handlers
     * for passing through declared or runtime exceptions.  These default handlers can be removed if necessary using the
     * removeHandlers() or clearHandlers() methods.  This method will be called on first invocation of getProxyBuilder()
     * so can make use of fields passed in by the constructor.
     *
     * @param handlerConfiguration the configuration to set up.
     */
    protected abstract void setUpHandlerConfiguration(HandlerConfiguration handlerConfiguration);

    /**
     * Returns the ProxyBuilder associated with this application.  The proxybuilder is used to create proxy objects.
     *
     * @return the proxy builder
     */
    protected ProxyBuilder getProxyBuilder() {
        if (proxyBuilder == null) {
            HandlerConfiguration handlerConfiguration = HandlerConfiguration.baselineConfiguration(getProxyType());
            setUpHandlerConfiguration(handlerConfiguration);
            ProxyEngine engine = (proxyEngine == null) ? new JavaProxyEngine() : proxyEngine;
            proxyBuilder = new ProxyBuilder(handlerConfiguration, engine);
        }
        return proxyBuilder;
    }

    /**
     * A simple name for this type of proxy.  It is used in the default toString() handler like "<PROXY_TYPE>
     * implementation of ..."
     *
     * @return a name for this proxy type.
     */
    protected String getProxyType() {
        return "Proxy";
    }

    protected Object create(ProxyObjectBuilder proxyObjectBuilder) {
        return getProxyBuilder().create(proxyObjectBuilder);
    }

    protected ProxyObjectBuilder proxy() {
        return new ProxyObjectBuilder();
    }

    public void setProxyEngine(ProxyEngine proxyEngine) {
        this.proxyBuilder = null;
        this.proxyEngine = proxyEngine;
    }
}
